package xj.toolkit.netty.initializer;

import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;

import org.apache.commons.lang3.StringUtils;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;

/**
 * JKS 方式存储证书以及秘钥。
 * 
 * @author <a href="mailto:cxj2000@gmail.com">xiaojian.cao</a>
 *
 */
public abstract class TcpServerInitializer extends SslBaseInitializer {

	private ChannelHandler tcpRequestHandler;
	private ChannelHandler tcpResponseEncoder;

	@Override
	protected void addCodecHandler(ChannelPipeline pipeline) throws Exception {
		pipeline.addLast("tcpRequestDecoder", getTcpRequestDecoder()).addLast("tcpResponseEncoder", tcpResponseEncoder);
	}

	@Override
	protected void addBusinessHandler(ChannelPipeline pipeline) throws Exception {
		pipeline.addLast("handler", tcpRequestHandler);
	}

	public void setTcpRequestHandler(ChannelHandler tcpRequestHandler) {
		this.tcpRequestHandler = tcpRequestHandler;
	}

	public void setTcpResponseEncoder(ChannelHandler tcpResponseEncoder) {
		this.tcpResponseEncoder = tcpResponseEncoder;
	}

	@Override
	public void initChannel(Channel ch) throws Exception {
		if (isUseSsl()) {

			if (getKeyStoreResource() == null || !getKeyStoreResource().exists()) {
				throw new Exception("Pls set keyStore file.");
			}

			if (StringUtils.isBlank(getPassword())) {
				throw new Exception("Pls set password.");
			}

			KeyStore keyStore = KeyStore.getInstance("JKS");
			keyStore.load(getKeyStoreResource().getInputStream(), getPassword().toCharArray());
			KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
			keyManagerFactory.init(keyStore, getPassword().toCharArray());

			SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(keyManagerFactory);

			// -- 客户端需要验证
			if (super.isClientNeedAuth()) {
				TrustManagerFactory tf = TrustManagerFactory.getInstance("SunX509");
				tf.init(keyStore);
				sslContextBuilder.trustManager(tf);
			}

			SslContext sslContext = sslContextBuilder.build();

			SSLEngine engine = sslContext.newEngine(ch.alloc());
			engine.setUseClientMode(false);
			if (isClientNeedAuth()) {
				engine.setNeedClientAuth(true);
			}
			ch.pipeline().addFirst("ssl", new SslHandler(engine));
		}

		super.initChannel(ch);
	}

	/**
	 * 注意tcpRequestDecoder必须确保是线程安全的 ,否则可能会出现解码时的未知异常
	 */
	public abstract ChannelHandler getTcpRequestDecoder();
}
